<?php
namespace App\Services;

use App\Exceptions\WechatException;
use GuzzleHttp\Client;
use Illuminate\Support\Facades\Cache;

class WechatService
{
    protected $appid;

    protected $secret;

    public function __construct($appid, $secret)
    {
        $this->appid = $appid;
        $this->secret = $secret;
    }

    /**
     * 获取微信网页授权链接
     * @param $redirectUrl
     * @param string $scope
     * @param string $state
     * @return string
     */
    public function getSnsapiUrl($redirectUrl, $scope = 'snsapi_base', $state = '')
    {
        $params = [
            'appid' => $this->appid,
            'redirect_uri' => ($redirectUrl),
            'response_type' => 'code',
            'scope' => $scope,
            'state' => $state
        ];
        return 'https://open.weixin.qq.com/connect/oauth2/authorize?' . http_build_query($params) . '#wechat_redirect';
    }

    /**
     * 获取用户的操作access token
     * @param $code
     * @return mixed
     * @throws WechatException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getAccessTokenByCode($code)
    {
        $api = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' . $this->appid . '&secret=' . $this->secret . '&code=' . $code . '&grant_type=authorization_code';
        $client = new CLient();
        $result = $client->get($api)->getBody();
        $resultArr = json_decode($result->getContents(), true);
        if (isset($resultArr['openid'])) {
            return $resultArr;
        }
        throw new WechatException($resultArr['errcode'] . ' => ' . $resultArr['errmsg']);
    }

    public function getJsapiTicket()
    {
        return Cache::remember('jsapi_ticket:' . $this->appid, 7000, function () {
            $accessToken = $this->getAccessToken();
            $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=' . $accessToken . '&type=jsapi';
            $client = new Client();
            $result = $client->get($url)->getBody();
            $resultArr = json_decode($result, true);
            if (empty($resultArr['ticket'])) {
                throw new WechatException('get ticket error. code:' . $resultArr['errcode'] . ' msg:' . $resultArr['errmsg']);
            }
            return $resultArr['ticket'];
        });
    }

    public function getAccessToken()
    {
        return Cache::remember('access_token:' . $this->appid, 7000, function () {
            $url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' . $this->appid . '&secret=' . $this->secret;
            $client = new Client();
            $result = $client->get($url)->getBody();
            $resultArr = json_decode($result, true);
            if (empty($resultArr['access_token'])) {
                throw new WechatException('get access_token error. code:' . $resultArr['errcode'] . ' msg:' . $resultArr['errmsg']);
            }
            return $resultArr['access_token'];
        });
    }



    public function getJssdkConfig($url = null)
    {
        // {debug:true, appId:'', timestamp:'', nonceStr:'', signature:'', jsApiList: ['chooseWXPay']}
        if (is_null($url)) {
            $url = request()->fullUrl();
        }
        $jsapiTicket = $this->getJsapiTicket();
        $params = [
            'jsapi_ticket' => $jsapiTicket,
            'noncestr' => md5(uniqid()),
            'timestamp' => time(),
            'url' => $url
        ];
        ksort($params);
        $params['signature'] = sha1(urldecode(http_build_query($params)));
        unset($params['url']);
        unset($params['jsapi_ticket']);
        return ['app_id' => $this->appid] + $params;
    }
}
